home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk12 / pspool1.0 / spool.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  15KB  |  466 lines

  1.  
  2. /* Spool.c    V1.0.0    27-Mar-88    ) Frangois Gagnon */
  3.  
  4.  
  5. /*
  6.    Copyright ) 1988  Frangois Gagnon,  All Rights Reserved.
  7.  
  8.    The author does not make any warranty expressed or implied,
  9.    or assumes any liability or responsiblity for the use of
  10.    this software.
  11.  
  12.    Permission is hereby granted to copy, reproduce, redistribute
  13.    or otherwise use this software as long as it is for non-profit.
  14.    This notice and the above copyright notice must remain intact
  15.    and appear on all copies.
  16.  
  17.    Permission is also granted to correct any problems with this
  18.    software, but modifications and improvements are reserved by
  19.    the author.
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24.  
  25. #include <exec/memory.h>
  26. #include <exec/ports.h>
  27. #include <exec/nodes.h>
  28. #include <libraries/dos.h>
  29. #include <intuition/preferences.h>
  30.  
  31. #include "stdefs.h"
  32. #include "Print_Spool.h"
  33.  
  34. /*********************************/
  35. /* Local Constants and Variables */
  36. /*********************************/
  37.  
  38. /* Define constant used in the program */
  39. #define Flag_Test       (Line_Formats | Page_Formats)
  40. #define Flag_Line       (Line_Density | Line_Formats)
  41. #define Flag_Page       (Page_Density | Page_Formats)
  42. #define Flag_Used       (Page_Density | Page_Formats | Opts_Headers)
  43. #define Opts_Page(Opts) ((Opts & Flag_Page) >> 3)
  44. #define Opts_Used(Opts) ((Opts & Flag_Used) >> 3)
  45.  
  46. local   int     Line_Size[8] = { 80, 96, 132, 80, 136, 164, 232, 136 };
  47. local   int     Page_Size[4] = { 51, 68, 66, 88 };
  48. local   int     Page_Used[8] = { 48, 64, 63, 84, 48, 63, 63, 83 };
  49. local   char    Line_Code[4] = { '0', '2', '4', '0' };
  50.  
  51. /* Declarations of status messages */
  52. local   char    HEAD[] = "\nSpool  V1.0  27-Mar-88  ) Frangois Gagnon\n\n";
  53. local   char    LOGS[] = "Spool: Unable to access log file.\n";
  54. local   char    EXEC[] = "Spool: Spool is already running.\n";
  55. local   char    INIT[] = "Spool: Unable to create a port.\n";
  56.  
  57. local   char    OPEN[] = "Unable to open %s for input.\n";
  58. local   char    COPY[] = "Printed %s ... %ld chars ... %ld lines ... %ld pages.\n";
  59. local   char    BACK[] = "Reset %s after %ld chars ... %ld lines ... %ld pages.\n";
  60. local   char    STOP[] = "Canceled %s after %ld chars ... %ld lines ... %ld pages.\n";
  61. local   char    MOVE[] = "Removed %s after %ld chars ... %ld lines ... %ld pages.\n";
  62.  
  63. /* Definition for Execution */
  64. local   FILE    *Spool_File;
  65. local   char    *Spool_Logs = "RAM:Spool.log";
  66.  
  67. local   struct  Inform  *Info_Port;
  68. local   struct  MsgPort *Data_Port;
  69.  
  70. local   Info    Status = { 1, Wait_State, 0, FALSE, 0, 0, 0, NULL };
  71.  
  72. local   FILE    *From_File, *Dest_File = NULL;
  73. local   short   Line_Limit, Line_Count;
  74. local   int     Char_Saved;
  75.  
  76. /* Definition for Manipulation */
  77. local   File    **Temp_Move, *Temp_File;
  78. local   File    **Temp_Skip, *Temp_Test;
  79. local   byte      Temp_Opts;
  80.  
  81. /* Simple typing optimization */
  82. #define Next_Char() { Char_Saved = fgetc( From_File); ++Status.Char_Print; }
  83.  
  84. /******************************/
  85. /* File Name Pattern Matching */
  86. /******************************/
  87.  
  88. local    int    File_Match( Name, Data)
  89. /*************************************/
  90. register char   *Name, *Data;
  91.  
  92. { auto     char *Save_Name[10],
  93.                 *Save_Data[10];
  94.   register int   Save;
  95.  
  96.   if ((*Data == NUL) || (*Name == NUL)) return FALSE;
  97.   Save = -1;
  98.  
  99.   while ((*Data != NUL) || (*Name != NUL))
  100.   { if (*Data == '*')
  101.     { if (*++Data == NUL) return TRUE;
  102.       if ( ++Save ==  10) return FALSE;
  103.       Save_Name[Save] = Name;
  104.       Save_Data[Save] = Data;
  105.       continue;
  106.     }
  107.     if (   ((*Data == '?') && (*Name != NUL))
  108.         || (toupper(*Data) == toupper(*Name)))
  109.     { ++Data; ++Name; continue; }
  110.  
  111.     if (*Name == NUL) --Save;
  112.     if ( Save <    0) return FALSE;
  113.     Name = ++Save_Name[Save];
  114.     Data =   Save_Data[Save];
  115.   }
  116.   return TRUE;
  117. }
  118.  
  119. /******************************/
  120. /* Initialization of Defaults */
  121. /******************************/
  122.  
  123. #define INTUITIONNAME           "intuition.library"
  124. public  struct IntuitionBase    *IntuitionBase;
  125.  
  126. local   void    Default_Values()
  127. /******************************/
  128.  
  129. { auto   struct Preferences     PrefBuffer;
  130.   auto   int                    Temp;
  131.   extern struct IntuitionBase  *OpenLibrary();
  132.   extern struct Preferences    *GetPrefs();
  133.  
  134.   /* Fetch the information from the system */
  135.   IntuitionBase = OpenLibrary( INTUITIONNAME, 0L);
  136.   if (IntuitionBase == NULL) return;
  137.   GetPrefs( &PrefBuffer, (long) sizeof( struct Preferences));
  138.   CloseLibrary( IntuitionBase);
  139.  
  140.   /* Extract the information from the structure */
  141.   Temp = (PrefBuffer.PrintSpacing == EIGHT_LPI ? 8 : 6);
  142.   if (PrefBuffer.PaperLength / Temp == 11) Status.Opts_State |= Page_11;
  143.   if (PrefBuffer.PaperSize == W_TRACTOR)   Status.Opts_State |= Line_13;
  144. }
  145.  
  146.  
  147. /**********************************/
  148. /* Stop Printing The Current File */
  149. /**********************************/
  150.  
  151. local   int     Stop_Printing( Spool_Show)
  152. /****************************************/
  153. char    *Spool_Show;
  154.  
  155. { extern FILE   *fopen();
  156.   if ((Status.Prog_State != Exec_State) &&
  157.       (Status.Prog_State != File_State) &&
  158.       (Status.Prog_State != Stop_State) ) return FALSE;
  159.  
  160.   if (Line_Count != Line_Limit) putc( '\f', Dest_File);
  161.   fclose( From_File);
  162.   if (Status.Prog_State == Exec_State)  Status.Prog_State = Wait_State;
  163.   else                                  Status.Prog_State = Susp_State;
  164.  
  165.   if ((Spool_File = fopen( Spool_Logs, "a")) == NULL) Spool_File = stderr;
  166.   fprintf( Spool_File,                   Spool_Show,
  167.            Status.File_Print->File_Name, Status.Char_Print,
  168.            Status.Line_Print,            Status.Page_Print);
  169.   if (Spool_File != stderr) fclose( Spool_File);
  170.   return TRUE;
  171. }
  172.  
  173. /********************************/
  174. /* Execute all pending commands */
  175. /********************************/
  176.  
  177. local   void    Exec_Print()
  178. /**************************/
  179.  
  180. { extern struct Inform  *GetMsg();
  181.   extern File           *AllocMem();
  182.   extern int             strncmp();
  183.  
  184.   while ((Info_Port = GetMsg( Data_Port)) != NULL)
  185.   { if (Info_Port->Number != PROTOCOL)
  186.       Info_Port->Number = PROTOCOL;
  187.     else switch( Info_Port->Action)
  188.     {
  189.       case PS_Insert :
  190.         Temp_Skip = &Status.File_Print;
  191.         while (*Temp_Skip) Temp_Skip = &(*Temp_Skip)->File_Next;
  192.         *Temp_Skip = Info_Port->Detail.Insert;
  193.         Info_Port->Detail.Insert = NULL;
  194.         break;
  195.  
  196.       case PS_Update :
  197.         for  (Temp_Test  = Info_Port->Detail.Update;
  198.               Temp_Test != NULL;
  199.               Temp_Test  = Temp_Test->File_Next)
  200.         {
  201.           for  (Temp_File  = Status.File_Print;
  202.                 Temp_File != NULL;
  203.                 Temp_File  = Temp_File->File_Next)
  204.           {
  205.             if (strncmp( Temp_Test->File_Name,
  206.                          Temp_File->File_Name, Name_Size) == 0)
  207.             { if ((Temp_Test->File_Copy == 0)      &&
  208.                   (Temp_File == Status.File_Print) ) Stop_Printing( STOP);
  209.               Temp_File->File_Opts  = Temp_Test->File_Opts;
  210.               Temp_File->File_Flag  = Temp_Test->File_Flag;
  211.               Temp_File->File_Copy  = Temp_Test->File_Copy;
  212.               Temp_File->File_Size  = Temp_Test->File_Size;
  213.               Temp_Test->File_Flag |= Flag_Updated;
  214.               break;
  215.         } } }
  216.         break;
  217.  
  218.       case PS_Remove :
  219.         Temp_Move = &Temp_File;
  220.         Temp_Skip = &Status.File_Print;
  221.         while ((Temp_Test = *Temp_Skip) != NULL)
  222.         { if (File_Match( Temp_Test->File_Name,
  223.                           Info_Port->Detail.Remove))
  224.           { if (Temp_Skip == &Status.File_Print) Stop_Printing( MOVE);
  225.             *Temp_Move = Temp_Test;
  226.             *Temp_Skip = Temp_Test->File_Next;
  227.             Temp_Move  = &Temp_Test->File_Next;
  228.           }
  229.           else Temp_Skip = &Temp_Test->File_Next;
  230.         }
  231.         *Temp_Move = NULL;
  232.         Info_Port->Detail.Insert = Temp_File;
  233.         break;
  234.  
  235.       case PS_Report :
  236.         Info_Port->Detail.Status = Status;
  237.         Temp_Skip = &Info_Port->Detail.Status.File_Print;
  238.         for (Temp_File  = Status.File_Print;
  239.              Temp_File != NULL;
  240.              Temp_File  = Temp_File->File_Next)
  241.         {
  242.           Temp_Test = AllocMem( (long) sizeof( File), MEMF_PUBLIC);
  243.           if (Temp_Test == NULL)
  244.           { Info_Port->Detail.Status.Opts_State |= Flag_Partial; }
  245.           else
  246.           { *(*Temp_Skip = Temp_Test) = *Temp_File;
  247.             Temp_Skip = &Temp_Test->File_Next;
  248.         } }
  249.         *Temp_Skip = NULL;
  250.         break;
  251.  
  252.       case PS_Return :
  253.         Status.Flag_State = !Status.Flag_State;
  254.         break;
  255.  
  256.       case PS_Change :
  257.         if (Status.File_Print != NULL)
  258.         { Status.Opts_State &= ~Flag_Test;
  259.           Status.Opts_State |= Status.File_Print->File_Opts & Flag_Test;
  260.         }
  261.         break;
  262.  
  263.       case PS_Freeze :
  264.         switch( Status.Prog_State)
  265.         { case Wait_State : case Page_State : case Open_State :
  266.             Status.Prog_State = Susp_State; break;
  267.           case Exec_State : case File_State :
  268.             Status.Prog_State = Stop_State; break;
  269.         }
  270.         break;
  271.  
  272.       case PS_Finish :
  273.           switch( Status.Prog_State)
  274.           { case Wait_State : case Page_State : case Open_State :
  275.               Status.Prog_State = Susp_State; break;
  276.             case Exec_State : case Stop_State :
  277.               Status.Prog_State = File_State; break;
  278.           }
  279.           break;
  280.           
  281.       case PS_Resets :
  282.         Stop_Printing( BACK);
  283.         Status.Prog_State = Susp_State;
  284.         break;
  285.  
  286.       case PS_Cancel :
  287.         if (Stop_Printing( STOP)) --Status.File_Print->File_Copy;
  288.         Status.Prog_State = Susp_State;
  289.         break;
  290.  
  291.       case PS_Resume :
  292.         if (Status.Prog_State == Susp_State) Status.Prog_State = Wait_State;
  293.         if (Status.Prog_State == Stop_State) Status.Prog_State = Exec_State;
  294.         if (Status.Prog_State == File_State) Status.Prog_State = Exec_State;
  295.         break;
  296.     }
  297.     Info_Port->Packet.mn_Node.ln_Type = NT_REPLYMSG;
  298.     ReplyMsg( Info_Port);
  299. } }
  300.  
  301. /******************************************/
  302. /* Perform according to the current state */
  303. /******************************************/
  304.  
  305. local   int     Exec_Spool()
  306. /**************************/
  307.  
  308. { extern FILE *fopen();
  309.  
  310.   switch( Status.Prog_State)
  311.   {
  312.     case Wait_State : case Page_State : case Open_State :
  313.  
  314.       /* Eliminate Old File Information */
  315.       while ((Temp_File = Status.File_Print) != NULL)
  316.       { if (Temp_File->File_Copy != 0) break;
  317.         Status.File_Print = Temp_File->File_Next;
  318.         if (Temp_File->File_Flag & Flag_Deleted)
  319.           remove( Temp_File->File_Name);
  320.         FreeMem( Temp_File, (long) sizeof( Temp_File));
  321.       }
  322.  
  323.       /* Wait if there is nothing to do */
  324.       if (Temp_File == NULL)
  325.       { Status.Prog_State = Wait_State;
  326.         if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  327.         if (Status.Flag_State)
  328.         { Forbid();
  329.           if ((Info_Port = GetMsg( Data_Port)) == NULL)
  330.           { DeletePort( Data_Port); Permit(); return FALSE; }
  331.           PutMsg( Data_Port, Info_Port);
  332.           Permit();
  333.         }
  334.         else WaitPort( Data_Port);
  335.         break;
  336.       }
  337.  
  338.       /* Check the format of the paper */
  339.       Temp_Opts = (Status.Opts_State ^ Temp_File->File_Opts);
  340.       if (Temp_Opts & Flag_Test)
  341.       { if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  342.         Status.Prog_State = Page_State;
  343.         WaitPort( Data_Port);
  344.         break;
  345.       }
  346.  
  347.       /* Request access to the printer */
  348.       if ((Dest_File                         == NULL) &&
  349.           ((Dest_File = fopen( "PRT:", "w")) == NULL) )
  350.       { Status.Prog_State = Open_State;
  351.         Delay( 5L * TICKS_PER_SECOND);
  352.         break;
  353.       }
  354.  
  355.       /* Request access to the data file */
  356.       From_File = fopen( Status.File_Print->File_Name, "r");
  357.       if (From_File == NULL)
  358.       { Status.File_Print->File_Copy = 0;
  359.         Status.Prog_State = Wait_State;
  360.  
  361.         Spool_File = fopen( Spool_Logs, "a");
  362.         if (Spool_File == NULL) Spool_File = stderr;
  363.         fprintf( Spool_File, OPEN, Status.File_Print->File_Name);
  364.         if (Spool_File != stderr) fclose( Spool_File);
  365.         break;
  366.       }
  367.  
  368.       /* Initialize all control variables */
  369.       Status.Opts_State = Status.File_Print->File_Opts;
  370.       Status.Char_Print = Status.Line_Print = Status.Page_Print = 0;
  371.  
  372.       Line_Limit = Page_Used[Opts_Used(Status.Opts_State)];
  373.       Line_Count = Line_Limit;
  374.  
  375.       /* Initialize the printer */
  376.       fprintf( Dest_File,
  377.         "\033c\033#1\033#5\033[%cw\033[1;%ds\033[%cz\033[%dt\033[%c\"z",
  378.         Line_Code[Status.Opts_State & Line_Density],
  379.         Line_Size[Status.Opts_State & Flag_Line],
  380.         (Status.Opts_State & Page_Density ? '0' : '1'),
  381.         Page_Size[Opts_Page(Status.Opts_State)],
  382.         (Status.File_Print->File_Flag & Flag_Quality ? '2' : '1'));
  383.         
  384.       /* Start printing the specified file */
  385.       Status.Prog_State = Exec_State;
  386.       Char_Saved        = fgetc( From_File);
  387.  
  388.     case Exec_State : case File_State :
  389.       /* Print the file one line at a time */
  390.       if (Char_Saved == EOF)
  391.       { Stop_Printing( COPY);
  392.         --Status.File_Print->File_Copy;
  393.         break;
  394.       }
  395.  
  396.       /* Deal with form feed characters */
  397.       if (Char_Saved == '\f')
  398.       { if (Line_Count != Line_Limit)
  399.         { putc( '\f', Dest_File); Line_Count = Line_Limit; }
  400.         Next_Char();
  401.         break;
  402.       }
  403.  
  404.       /* Deal with page counters and headers */
  405.       if (Line_Count == Line_Limit)
  406.       { ++Status.Page_Print; Line_Count = 0;
  407.         if (Status.Opts_State & Opts_Headers)
  408.         { fprintf( Dest_File, "%-20.20s    %-42.42s    Page %3ld\n\n\n",
  409.                    Status.File_Print->File_Date,
  410.                    Status.File_Print->File_Name,
  411.                    Status.Page_Print);
  412.           Line_Count = 3;
  413.       } }
  414.  
  415.       /* Time to print the line */
  416.       ++Status.Line_Print; ++Line_Count;
  417.       if (Status.Opts_State & Opts_Numbers)
  418.         fprintf( Dest_File, "%6ld: ", Status.Line_Print);
  419.       while ((Char_Saved !=  EOF) &&
  420.              (Char_Saved != '\n') &&
  421.              (Char_Saved != '\f') )
  422.       { putc( Char_Saved, Dest_File); Next_Char(); }
  423.       if (Char_Saved == '\n') Next_Char();
  424.       fputs( (Line_Count == Line_Limit ? "\n\f" : "\n"), Dest_File);
  425.       break;
  426.  
  427.     case Susp_State :
  428.       /* Wait for new comamnds */
  429.       if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  430.     case Stop_State :
  431.       WaitPort( Data_Port);
  432.       break;
  433.   }
  434.   return TRUE;
  435. }
  436.  
  437. /*****************************/
  438. /* This is the Spool program */
  439. /*****************************/
  440.  
  441. public  void    main( argc, argv)
  442. /*******************************/
  443. int      argc;
  444. char    *argv[];
  445.  
  446. { extern struct MsgPort *FindPort(), *CreatePort();
  447.   extern FILE           *fopen();
  448.  
  449.   fprintf( stderr, HEAD);
  450.   if (FindPort( SPOOLNAME) != NULL)
  451.   { fprintf( stderr, EXEC); exit( 1); }
  452.  
  453.   if (argc > 1) Spool_Logs = argv[1];
  454.   if ((Spool_File = fopen( Spool_Logs, "a")) == NULL)
  455.   { fprintf( stderr, LOGS, Spool_Logs); exit(1); }
  456.   fprintf( Spool_File, HEAD);
  457.   fclose( Spool_File);
  458.  
  459.   if ((Data_Port = CreatePort( SPOOLNAME, 0L)) == NULL)
  460.   { fprintf( stderr, INIT); exit( 1); }
  461.   Default_Values();
  462.  
  463.   do Exec_Print();
  464.   while (Exec_Spool());
  465. }
  466.